/*
 * @Author: Clark
 * @Email: haixuanwoTxh@gmail.com
 * @Date: 2021-10-20 20:45:20
 * @LastEditors: Clark
 * @LastEditTime: 2021-12-14 11:57:39
 * @Description: file content
 */

#ifndef TALK_PROTOCOL_H
#define TALK_PROTOCOL_H

#include <string>
#include <iostream>
#include <stdio.h>

#define HEAD 0xFFFF
#define END  0xEEEE
#define BASIC_PACKET_LEN 10 // HEAD包头2字节+Action2字节+包长2字节+checksum2字节+END2字节

#define USR_MAX_LEN 64
#define PASSWD_MAX_LEN 64

/**
 * @brief 功能行为
 */
typedef enum
{
	LOGIN,				// 登录
	LOGUP,				// 注册
	MESSAGE,			// 聊天消息
	LOGOUT,				// 登出
	PUBLIC_CLIENT_INFO,	// 发布客户信息
	INVALID_ACTION		// 无效的行为
}Action;

/**
 * @brief 协议包数据结构
 * ---------------------------------------------------------------------------------------------------
 * | head   | Action  |      data len    | data  | checksum                                |  end    |
 * | 0xFFFF | 2Byte   |  只数据长度，2Byte |   ... | Action + data len + data字节累加和，2Byte |  0xEEEE |
 * ---------------------------------------------------------------------------------------------------
 */

/**
 * @brief 服务端与客户端交互协议
 */
class TalkProtocol
{
public:
	/**
	 * @brief 以十六进制打印
	 * @param data	数据
	 * @param dataLen 数据长度
	 */
	void print_data_as_hex(unsigned char *data, int dataLen);

	/**
	 * @brief 设置数值到2字节空间
	 * @param value 数值
	 * @param buf 设置的地址
	 */
	void set_value_to_2Byte_buf(unsigned short value, unsigned char *buf);

	/**
	 * @brief 获取2字节空间中的数值
	 * @param  buf 获取的地址
	 * @param  value 获取的数值
	 */
	void get_value_from_2Byte_buf(unsigned char *buf, unsigned short &value);

	/**
	 * @brief 设置数值到4字节空间
	 * @param value 设置的数值
	 * @param buf 设置地址
	 */
	void set_value_to_4Byte_buf(unsigned int value, unsigned char *buf);

	/**
	 * @brief 获取4字节空间中的数值
	 * @param  buf 获取地址
	 * @param  value 获取的数值
	 */
	void get_value_from_4Byte_buf(unsigned char *buf, unsigned int &value);

	/**
	 * @brief 获取校验码，数据的字节累加和
	 * @param data 		数据
	 * @param dataLen	数据长度
	 * @param checksum	校验码结果
	 * @return true		成功
	 * @return false	失败
	 */
	bool get_checksum(unsigned char *data, int dataLen, unsigned short &checksum);

	/**
	 * @brief 构建协议包
	 * @param action  	包行为类型
	 * @param data		包数据
	 * @param dataLen	数据长度
	 * @param packet	存放数据包的缓存
	 * @param packetBufSize	缓存空间大小
	 * @param packetLen	包大小
	 * @return true		成功
	 * @return false	失败
	 */
	bool build_protocol_packet(Action action, unsigned char* data, int dataLen, unsigned char* packet, int packetBufSize, int &packetLen);

	/**
	 * @brief 解析协议包
	 * @param packet	包内容
	 * @param packetLen	包长度
	 * @param action	解析出的包行为类型
	 * @param data		解析出的数据
	 * @param dataBufSize	存储数据缓存大小
	 * @param dataLen	数据长度
	 * @return true		成功
	 * @return false	失败
	 */
	bool parse_protocol_packet(unsigned char* packet, int packetLen, Action &action, unsigned char* data, int dataBufSize, int &dataLen);

	/**
	 * @brief 从数据中获取用户名和密码
	 * @param data		数据
	 * @param dataLen	数据长度
	 * @param user		用户名
	 * @param passwd	密码
	 * @return true		成功
	 * @return false	失败
	 */
	bool get_name_passwd(unsigned char *data, int dataLen, std::string &user, std::string &passwd);
};

#endif
